From: Keir Fraser Date: Mon, 7 Sep 2009 07:46:46 +0000 (+0100) Subject: Add the support of x2apic logical cluster mode. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13371 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=b8fae2f7774ee716e2aa6eda67624fc61ab31bce;p=xen.git Add the support of x2apic logical cluster mode. Add a xen boolean parameter 'x2apic'. Add a xen boolean parameter 'x2apic_phys'(by default, we use logical cluster mode). Signed-off-by: Dexuan Cui --- diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 47d614269e..ba6b0dbb3d 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -848,8 +848,31 @@ void enable_x2apic(void) { u32 lo, hi; - if ( !iommu_supports_eim() ) - return; + if ( smp_processor_id() == 0 ) + { + if ( !iommu_supports_eim() ) + { + printk("x2APIC would not be enabled without EIM.\n"); + return; + } + + if ( apic_x2apic_phys.probe() ) + genapic = &apic_x2apic_phys; + else if ( apic_x2apic_cluster.probe() ) + genapic = &apic_x2apic_cluster; + else + { + printk("x2APIC would not be enabled due to x2apic=off.\n"); + return; + } + + x2apic_enabled = 1; + printk("Switched to APIC driver %s.\n", genapic->name); + } + else + { + BUG_ON(!x2apic_enabled); /* APs only enable x2apic when BSP did so. */ + } rdmsr(MSR_IA32_APICBASE, lo, hi); if ( !(lo & MSR_IA32_APICBASE_EXTD) ) @@ -860,14 +883,6 @@ void enable_x2apic(void) } else printk("x2APIC mode enabled by BIOS.\n"); - - if ( !x2apic_enabled ) - { - x2apic_enabled = 1; - genapic = &apic_x2apic; - printk(KERN_INFO "Switched to APIC driver %s.\n", - genapic->name); - } } void __init init_apic_mappings(void) diff --git a/xen/arch/x86/genapic/x2apic.c b/xen/arch/x86/genapic/x2apic.c index 40d54e4d22..c57a66eeac 100644 --- a/xen/arch/x86/genapic/x2apic.c +++ b/xen/arch/x86/genapic/x2apic.c @@ -23,25 +23,46 @@ #include #include -__init int probe_x2apic(void) +static int x2apic = 1; +boolean_param("x2apic", x2apic); + +static int x2apic_phys = 0; /* By default we use logical cluster mode. */ +boolean_param("x2apic_phys", x2apic_phys); + +__init int probe_x2apic_phys(void) +{ + return x2apic && x2apic_phys && x2apic_is_available() && + iommu_supports_eim(); +} + +__init int probe_x2apic_cluster(void) { - return x2apic_is_available(); + return x2apic && !x2apic_phys && x2apic_is_available() && + iommu_supports_eim(); } -struct genapic apic_x2apic= { - APIC_INIT("x2apic", probe_x2apic), - GENAPIC_X2APIC +struct genapic apic_x2apic_phys= { + APIC_INIT("x2apic_phys", probe_x2apic_phys), + GENAPIC_X2APIC_PHYS +}; + +struct genapic apic_x2apic_cluster= { + APIC_INIT("x2apic_cluster", probe_x2apic_cluster), + GENAPIC_X2APIC_CLUSTER }; -void init_apic_ldr_x2apic(void) +void init_apic_ldr_x2apic_phys(void) { - /* We only use physical delivery mode. */ return; } +void init_apic_ldr_x2apic_cluster(void) +{ + int cpu = smp_processor_id(); + cpu_2_logical_apicid[cpu] = apic_read(APIC_LDR); +} void clustered_apic_check_x2apic(void) { - /* We only use physical delivery mode. */ return; } @@ -55,12 +76,17 @@ cpumask_t vector_allocation_domain_x2apic(int cpu) return cpumask_of_cpu(cpu); } -unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask) +unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask) { return cpu_physical_id(first_cpu(cpumask)); } -void send_IPI_mask_x2apic(const cpumask_t *cpumask, int vector) +unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask) +{ + return cpu_2_logical_apicid[first_cpu(cpumask)]; +} + +void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector) { unsigned int cpu, cfg; unsigned long flags; @@ -87,3 +113,19 @@ void send_IPI_mask_x2apic(const cpumask_t *cpumask, int vector) local_irq_restore(flags); } +void send_IPI_mask_x2apic_cluster(const cpumask_t *cpumask, int vector) +{ + unsigned int cpu, cfg; + unsigned long flags; + + mb(); /* see the comment in send_IPI_mask_x2apic_phys() */ + + local_irq_save(flags); + + cfg = APIC_DM_FIXED | 0 /* no shorthand */ | APIC_DEST_LOGICAL | vector; + for_each_cpu_mask ( cpu, *cpumask ) + if ( cpu != smp_processor_id() ) + apic_wrmsr(APIC_ICR, cfg, cpu_2_logical_apicid[cpu]); + + local_irq_restore(flags); +} diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h index 2eef80e23e..ccb772a2f1 100644 --- a/xen/include/asm-x86/genapic.h +++ b/xen/include/asm-x86/genapic.h @@ -49,7 +49,8 @@ struct genapic { APICFUNC(acpi_madt_oem_check) extern struct genapic *genapic; -extern struct genapic apic_x2apic; +extern struct genapic apic_x2apic_phys; +extern struct genapic apic_x2apic_cluster; void init_apic_ldr_flat(void); void clustered_apic_check_flat(void); @@ -69,24 +70,38 @@ cpumask_t vector_allocation_domain_flat(int cpu); .send_IPI_mask = send_IPI_mask_flat, \ .send_IPI_self = send_IPI_self_flat -void init_apic_ldr_x2apic(void); +void init_apic_ldr_x2apic_phys(void); +void init_apic_ldr_x2apic_cluster(void); void clustered_apic_check_x2apic(void); cpumask_t target_cpus_x2apic(void); -unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask); -void send_IPI_mask_x2apic(const cpumask_t *mask, int vector); +unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask); +unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask); +void send_IPI_mask_x2apic_phys(const cpumask_t *mask, int vector); +void send_IPI_mask_x2apic_cluster(const cpumask_t *mask, int vector); void send_IPI_self_x2apic(int vector); cpumask_t vector_allocation_domain_x2apic(int cpu); -#define GENAPIC_X2APIC \ +#define GENAPIC_X2APIC_PHYS \ .int_delivery_mode = dest_Fixed, \ .int_dest_mode = 0 /* physical delivery */, \ - .init_apic_ldr = init_apic_ldr_x2apic, \ + .init_apic_ldr = init_apic_ldr_x2apic_phys, \ .clustered_apic_check = clustered_apic_check_x2apic, \ .target_cpus = target_cpus_x2apic, \ .vector_allocation_domain = vector_allocation_domain_x2apic, \ - .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic, \ - .send_IPI_mask = send_IPI_mask_x2apic, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_phys, \ + .send_IPI_mask = send_IPI_mask_x2apic_phys, \ .send_IPI_self = send_IPI_self_x2apic +#define GENAPIC_X2APIC_CLUSTER \ + .int_delivery_mode = dest_LowestPrio, \ + .int_dest_mode = 1 /* logical delivery */, \ + .init_apic_ldr = init_apic_ldr_x2apic_cluster, \ + .clustered_apic_check = clustered_apic_check_x2apic, \ + .target_cpus = target_cpus_x2apic, \ + .vector_allocation_domain = vector_allocation_domain_x2apic, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_cluster, \ + .send_IPI_mask = send_IPI_mask_x2apic_cluster, \ + .send_IPI_self = send_IPI_self_x2apic + void init_apic_ldr_phys(void); void clustered_apic_check_phys(void); cpumask_t target_cpus_phys(void);